﻿using Caching;
using SmallJob.Model;
using SmallJob.Services.Code;
using SmallJob.Services.Implements;
using SmallJob.Services.Interfaces;
using SmallShop.Services.Code;
using SmallShop.Services.Implements;
using SmallShop.Services.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;

namespace FrontEnd.Controllers
{
    public class PersonalController : Controller
    {
        private readonly IEmailFormatService _EmailFormatService;
        private readonly IMessageService _MessageService;
        private readonly IOrderService _OrderService;
        private readonly IProvideService _ProvideService;
        private readonly ISkillService _SkillService;
        private readonly IUserService _UserService;
        private readonly IRequestService _RequestService;
        private readonly ITransactionService _TransactionService;
        private readonly IMMessageService _MMessageService;
        private readonly IMConversationService _MConversationService;

        public PersonalController(ITransactionService TransactionService, IUserService UserService, ISkillService SkillService, IMessageService MessageService, IProvideService ProvideService, IOrderService OrderService, IEmailFormatService EmailFormatService, IRequestService RequestService, IMMessageService MMessageService, IMConversationService MConversationService)
        {
            _UserService = UserService;
            _TransactionService = TransactionService;
            _SkillService = SkillService;
            _MessageService = MessageService;
            _ProvideService = ProvideService;
            _OrderService = OrderService;
            _EmailFormatService = EmailFormatService;
            _RequestService = RequestService;
            _MMessageService = MMessageService;
            _MConversationService = MConversationService;
        }

        [HttpPost]
        public ActionResult SaveAccount(string oldpassword, string newpassword, string repassword)
        {
            if (!User.Identity.IsAuthenticated)
            {
                return Json(false);
            }
            var user = _UserService.GetByFBID(User.Identity.Name) ?? _UserService.GetByEmail(User.Identity.Name);
            string storepassword = "";
            if (!user.Password.Equals(UserUtility.Encrypt(oldpassword, user.Email)))
            {
                ModelState.AddModelError("OldPasswordInvalid", "Mật khẩu cũ nhập không đúng!");
                oldpassword = "Mật khẩu cũ nhập không đúng!";
            }
            else oldpassword = "";
            if ((string.IsNullOrWhiteSpace(newpassword) || newpassword.Length < 6))
            {
                ModelState.AddModelError("PasswordInvalid", "Mật khẩu gồm ít nhất 6 kí tự");
                newpassword = "Mật khẩu gồm ít nhất 6 kí tự";
            }
            else
            {
                storepassword = newpassword;
                newpassword = "";
            }
            if (storepassword != repassword)
            {
                ModelState.AddModelError("Re-PasswordInvalid", "Mật khẩu nhập lại không đúng");
                repassword = "Mật khẩu nhập lại không đúng";
            }
            else
            {
                repassword = "";
            }
            if (ModelState.IsValid)
            {
                user.Password = UserUtility.Encrypt(storepassword, user.Email);
                _UserService.Update(user);
                return Json(true);
            }

            return Json(new { oldpassword = oldpassword, newpassword = newpassword, repassword = repassword });
        }

        [HttpPost]
        public ActionResult SaveProfile(string storename, string propername, string city, string job, string phone, string skills)
        {
            if (!User.Identity.IsAuthenticated)
            {
                return Json(false);
            }
            var user = _UserService.GetByFBID(User.Identity.Name) ?? _UserService.GetByEmail(User.Identity.Name);
            int intTemp = 0;
            if (!string.IsNullOrWhiteSpace(storename))
            {
                if (storename.Length < 4)
                {
                    storename = "Nickname nên dài hơn hoặc bằng 4 ký tự.";
                    ModelState.AddModelError("storename", storename);
                }
                else
                {
                    if (!storename.Equals(user.UserName) && _UserService.CheckUserNameExist(storename))
                    {
                        storename = "Nickname đã được dùng.";
                        ModelState.AddModelError("storename", storename);
                    }
                    else if (StringHanding.HasSpecialCharacters(storename))
                    {
                        storename = "Store name không thể nhập ký tự đặc biệt.";
                        ModelState.AddModelError("storename", storename);
                    }
                    else if (Int32.TryParse(storename, out intTemp))
                    {
                        storename = "Store name không thể chỉ nhập số.";
                        ModelState.AddModelError("storename", storename);
                    }
                    else
                    {
                        user.UserName = storename;
                        storename = "";
                    }
                }
            }

            if (!string.IsNullOrWhiteSpace(propername))
            {
                user.ProperName = propername;
            }
            //set to string empty after assign to user and return json as no error
            propername = "";
            user.Location = city;
            city = "";
            user.Job = job;
            job = "";
            if (!string.IsNullOrWhiteSpace(phone))
            {
                if (!UserUtility.CheckPhone(phone))
                {
                    ModelState.AddModelError("phoneerror", "Wrong format");
                    phone = "Sai định dạng,Số điện thoại sai!";
                }
                else
                {
                    user.Phone = phone;
                    phone = "";
                }
            }
            //user.Skills = skills;
            skills = "";

            if (ModelState.IsValid)
            {
                _UserService.Update(user);
                return Json(true);
            }
            return Json(new { storename = storename, propername = propername, city = city, job = job, phone = phone, skills = skills });
        }

        public ActionResult ConversationPV(string pageforload)
        {
            if (!User.Identity.IsAuthenticated) return Json("");
            var user = _UserService.GetByFBID(User.Identity.Name) ?? _UserService.GetByEmail(User.Identity.Name);
            var mesid = Request.Form["cvsId"];
            var cvs = _MConversationService.GetConversationByShortID(mesid);
            var pagesize = Convert.ToInt32(Resources.Resource.MessagePerPage);
            long total = 0;
            var pageload = 1;
            if (!string.IsNullOrWhiteSpace(pageforload))
            {
                pageload = Convert.ToInt32(pageforload);
            }
            cvs.Messages = _MMessageService.GetMessagesByPage(pageload, pagesize, out total, cvs.ShortID);
            var model = cvs;
            foreach (var item in model.Messages)
            {
                if (item.ReceiverID == user.ID)
                {
                    if (!item.IsRead)
                    {
                        item.IsRead = true;
                        _MMessageService.UpdateStatusMessage(item);
                    }
                }
            }
            if (total > (pageload * pagesize))
            {
                ViewData["nextpage"] = pageload + 1;
            }
            ViewData["curuserid"] = user.ID;
            return PartialView(model);
        }

        public ActionResult Inbox()
        {
            if (!User.Identity.IsAuthenticated) return RedirectToAction("Index", "Home");
            var user = UtilityService.GetLoginUser(_UserService, User);
            //var conversations = _MConversationService.GetConversationByID(user.ID);
            var conversations = new List<MConversation>();
            var pagesize = Convert.ToInt32(Resources.Resource.ConversationPerPage);
            long totalprovide = 0;
            long totalrequest = 0;
            conversations.AddRange(_MConversationService.GetConversationByPage(1, pagesize, out totalprovide, user.ID, (int)MessageType.PROVIDE));
            conversations.AddRange(_MConversationService.GetConversationByPage(1, pagesize, out totalrequest, user.ID, (int)MessageType.REQUEST));
            ViewData["lstmes"] = conversations;
            ViewData["curuserid"] = user.ID;
            ViewData["nextpageprovide"] = 0;
            ViewData["nextpagerequest"] = 0;
            if (totalprovide > (1 * pagesize))
            {
                ViewData["nextpageprovide"] = 1 + 1;
            }
            if (totalrequest > (1 * pagesize))
            {
                ViewData["nextpagerequest"] = 1 + 1;
            }
            return View();
        }

        public ActionResult Order()
        {
            if (!User.Identity.IsAuthenticated) { return RedirectToAction("Index", "Home"); }
            var user = UtilityService.GetLoginUser(_UserService, User);
            //var orders = _OrderService.GetAllOrderByUserId(user.ID);
            ViewData["owner"] = user;
            var conversations = new List<MConversation>();
            var pagesize = Convert.ToInt32(Resources.Resource.ConversationPerPage);
            long totalsell = 0;
            long totalbuy = 0;
            conversations.AddRange(_MConversationService.GetConversationOrderByPage(1, pagesize, out totalsell, user.ID, true));
            conversations.AddRange(_MConversationService.GetConversationOrderByPage(1, pagesize, out totalbuy, user.ID, false));
            conversations = conversations.OrderByDescending(c => c.Message.Date).ToList();
            ViewData["lstmes"] = conversations;
            if (totalsell > (1 * pagesize))
            {
                ViewData["nextpagesell"] = 1 + 1;
            }
            if (totalbuy > (1 * pagesize))
            {
                ViewData["nextpagebuy"] = 1 + 1;
            }
            return View();
        }

        public ActionResult OrderDetailPV()
        {
            if (!User.Identity.IsAuthenticated) return Json("");
            var user = _UserService.GetByFBID(User.Identity.Name) ?? _UserService.GetByEmail(User.Identity.Name);
            var cvsid = Request.Form["cvsid"];
            var cvs = _MConversationService.GetConversationByShortID(cvsid);
            var order = _OrderService.GetById(Convert.ToInt32(cvsid.Substring(0, cvsid.Length - 1)));
            if (user.ID != order.BuyerID && user.ID != order.SellerID) return HttpNotFound("Cannot access.");
            var pagesize = Convert.ToInt32(Resources.Resource.MessagePerPage);
            long total = 0;
            cvs.Messages = _MMessageService.GetMessagesByPage(1, pagesize, out total, cvs.ShortID);
            var model = cvs;
            foreach (var item in model.Messages)
            {
                if (item.ReceiverID == user.ID)
                {
                    if (!item.IsRead)
                    {
                        item.IsRead = true;
                        _MMessageService.UpdateStatusMessage(item);
                    }
                }
            }
            if (total > (1 * pagesize))
            {
                ViewData["nextpage"] = 2;
            }
            ViewData["curuserid"] = user.ID;
            ViewData["displayorder"] = order;
            ViewData["isbuyer"] = (user.ID == order.BuyerID);
            return PartialView(model);
        }

        public ActionResult SendMessage()
        {
            if (!User.Identity.IsAuthenticated)
            {
                return Json(false);
            }
            var mes = Request.Form["mes"];
            var cvsid = Request.Form["preId"];
            var user = _UserService.GetByFBID(User.Identity.Name) ?? _UserService.GetByEmail(User.Identity.Name);
            var cvs = _MConversationService.GetConversationByShortID(cvsid);
            var receiverid = (user.ID == cvs.Person1ID ? cvs.Person2ID : cvs.Person1ID);
            string titleservice = "";
            if (cvs.Order != null)
            {
                titleservice = (cvs.Order.Provide == null ? cvs.Order.Request.Title : cvs.Order.Provide.Title);
            }
            else
            {
                titleservice = (cvs.Provide == null ? cvs.Request.Title : cvs.Provide.Title);
            }
            MMessage m = new MMessage()
            {
                Content = mes,
                Date = DateTime.Now,
                IsRead = false,
                ParentID = cvsid,
                ReceiverID = receiverid,
                SenderID = user.ID,
                Type = cvs.Type
            };
            _MMessageService.Add(m);
            _MConversationService.UpdateLastMessage(cvsid, m);
            var unread = _MMessageService.CountUnread(receiverid);
            MessageHelper.SendMessageNotifyMessage(_MMessageService, Resources.Resource.SystemNotifyQuestion, unread, Resources.Resource.NumberMessageToNotify, receiverid, false);
            //send notify
            //try catch to enable and disable send email depend on resource
            EmailFormat format = null;
            DictionaryMessage dicmes = null;
            var receiver = _UserService.GetById(receiverid);
            try
            {
                format = _EmailFormatService.GetById(Convert.ToInt32(Resources.Resource.NotifyEmailMessage));
                var email = UserUtility.GetVerifiedEmail(receiver);
                dicmes = new DictionaryMessage(email, user.ProperName, titleservice, cvsid);
                UserUtility.NotifyEmail(format, dicmes);
            }
            catch (Exception) { }
            if (cvs.Request != null)
            {
                var request = _RequestService.GetById(cvs.Request.ID);
                if (!string.IsNullOrWhiteSpace(request.ForwardEmail))
                {
                    try
                    {
                        format = _EmailFormatService.GetById(Convert.ToInt32(Resources.Resource.NotifyEmailForwardMessage));
                        dicmes = new DictionaryForwardMessage(request.ForwardEmail, user.ProperName, request.Title, cvsid, m.Content);
                        UserUtility.NotifyEmail(format, dicmes);
                    }
                    catch (Exception) { }
                }
            }
            var model = cvs;
            cvs.Message = m;
            var lst = new List<MMessage>();
            lst.Add(m);
            cvs.Messages = lst;
            ViewData["curuserid"] = user.ID;
            return PartialView("ConversationPV", model);
        }

        //public ActionResult MakeDoneOrder(int orderid)
        //{
        //    if (!User.Identity.IsAuthenticated) return Json(new { result = false });
        //    var order = _OrderService.GetById(orderid);
        //    if (order == null) return Json(new { result = false });
        //    order.Completed = true;
        //    order.Status = (int)OrderStatusV2.Done;
        //    order.ModifiedDate = DateTime.Now;
        //    var transaction = _TransactionService.GetTransactionForOrder(order.BuyerID, order.SellerID, order.ProvideID);
        //    if (transaction == null) return Json(new { result = false });
        //    _OrderService.Update(order);
        //    //chuyển tiền cho người bán và đổi status transaction
        //    transaction.Status = (int)ETransactionStatus.Receiver_Receive_Success;
        //    _TransactionService.Update(transaction);
        //    _MConversationService.MakeCvsNoDisplay(MessageHelper.BuildShortIDOrder(order.ID));
        //    return Json(new { result = true });
        //}

        public ActionResult MakeCancelOrder(int orderid)
        {
            if (!User.Identity.IsAuthenticated) return Json(new { result = false });
            var order = _OrderService.GetById(orderid);
            if (order == null) return Json(new { result = false });
            if (order.Completed) return Json(new { result = false });
            order.IsDeleted = true;
            order.Status = (int)OrderStatusV2.Cancel;
            order.ModifiedDate = DateTime.Now;
            var transaction = _TransactionService.GetTransactionForOrder(order.BuyerID, order.SellerID, order.ProvideID);
            if (transaction == null) return Json(new { result = false });
            _OrderService.Update(order);
            transaction.Status = (int)ETransactionStatus.Receiver_Receive_Cancel;
            _TransactionService.Update(transaction);
            _MConversationService.MakeCvsNoDisplay(MessageHelper.BuildShortIDOrder(order.ID));
            return Json(new { result = true });
        }

        public ActionResult CommentOrder(int orderid, string comment)
        {
            if (!User.Identity.IsAuthenticated) return Json(new { result = false });
            var user = UtilityService.GetLoginUser(_UserService, User);
            var order = _OrderService.GetById(orderid);
            if (order == null) return Json(new { result = false });
            order.Comment = comment;
            order.ModifiedDate = DateTime.Now;
            _OrderService.Update(order);
            var orders = MemCache.Get<List<Order>>("user_comment_" + user.ID);
            if (orders != null)
            {
                order.Buyer = _UserService.GetById(order.BuyerID);
                orders.Add(order);
                orders = orders.OrderByDescending(o => o.ModifiedDate).ToList();
                MemCache.InsertCache("user_comment_" + order.SellerID, orders);
            }
            return Json(new { result = true });
        }

        public ActionResult RateOrder(int orderid, string rate)
        {
            if (!User.Identity.IsAuthenticated) return Json(new { result = false });
            var order = _OrderService.GetById(orderid);
            if (order == null) return Json(new { result = false });
            order.Rate = Convert.ToByte(rate);
            order.ModifiedDate = DateTime.Now;
            _OrderService.Update(order);
            return Json(new { result = true });
        }

        public ActionResult LoadMoreCvsPV(int type, int page)
        {
            if (!User.Identity.IsAuthenticated) return RedirectToAction("Index", "Home");
            var user = UtilityService.GetLoginUser(_UserService, User);
            //var conversations = _MConversationService.GetConversationByID(user.ID);
            var conversations = new List<MConversation>();
            var pagesize = Convert.ToInt32(Resources.Resource.ConversationPerPage);
            long total = 0;
            conversations.AddRange(_MConversationService.GetConversationByPage(page, pagesize, out total, user.ID, type));
            ViewData["lstmes"] = conversations;
            ViewData["curuserid"] = user.ID;
            if (total > (page * pagesize))
            {
                ViewData["nextpage"] = page + 1;
            }
            return PartialView();
        }

        public ActionResult LoadMoreCvsOrderPV(bool isordersell, int page)
        {
            if (!User.Identity.IsAuthenticated) return RedirectToAction("Index", "Home");
            var user = UtilityService.GetLoginUser(_UserService, User);
            //var conversations = _MConversationService.GetConversationByID(user.ID);
            var conversations = new List<MConversation>();
            var pagesize = Convert.ToInt32(Resources.Resource.ConversationPerPage);
            long total = 0;
            conversations.AddRange(_MConversationService.GetConversationOrderByPage(page, pagesize, out total, user.ID, isordersell));
            ViewData["lstmes"] = conversations;
            ViewData["curuserid"] = user.ID;
            ViewData["owner"] = user;
            if (total > (page * pagesize))
            {
                ViewData["nextpage"] = page + 1;
            }
            return PartialView();
        }

        public ActionResult OrderDetails(string cvsid)
        {
            if (!User.Identity.IsAuthenticated) return RedirectToAction("Index", "Home");
            var user = UtilityService.GetLoginUser(_UserService, User);
            var order = _OrderService.GetById(Convert.ToInt32(cvsid.Substring(0, cvsid.Length - 1)));
            if (user.ID != order.BuyerID && user.ID != order.SellerID) return HttpNotFound("Cannot access.");

            var current = DateTime.Now;
            if (order.Status == (int)OrderStatusV2.InProgress)
            {
                var remain = (DateTime)order.Deadline - current;
                if (remain.TotalDays < -3)
                {
                    order.Status = (int)OrderStatusV2.Failed;
                    order.Rate = 1;
                    order.Comment = Resources.Resource.SystemCommentFailedOrder;
                    order.ModifiedDate = current;
                    _OrderService.Update(order);
                }
            }
            else if (order.Status == (int)OrderStatusV2.WaitDone)
            {
                var remain = order.ModifiedDate - current;
                if (remain.TotalDays < -3)
                {
                    order.Status = (int)OrderStatusV2.Done;
                    order.ModifiedDate = current;
                    _OrderService.Update(order);
                }
            }

            if (order.Type == (int)OrderType.PROVIDE)
            {
                order.Provide = _ProvideService.GetById(order.ProvideID);
            }
            else
            {
                order.Request = _RequestService.GetById(order.RequestID);
            }
            var cvs = _MConversationService.GetConversationByShortID(cvsid);
            var pagesize = Convert.ToInt32(Resources.Resource.MessagePerPage);
            long total = 0;
            cvs.Messages = _MMessageService.GetMessagesByShortID(cvs.ShortID);
            var model = cvs;
            foreach (var item in model.Messages)
            {
                if (item.ReceiverID == user.ID)
                {
                    if (!item.IsRead)
                    {
                        item.IsRead = true;
                        _MMessageService.UpdateStatusMessage(item);
                    }
                }
            }


            if (total > (1 * pagesize))
            {
                ViewData["nextpage"] = 2;
            }
            ViewData["curuserid"] = user.ID;
            ViewData["displayorder"] = order;
            return View(model);
        }

        public ActionResult MakeAcceptOrder(int orderid)
        {
            if (!User.Identity.IsAuthenticated) return Json(new { result = false });
            var user = UtilityService.GetLoginUser(_UserService, User);
            var order = _OrderService.GetById(orderid);
            if (order == null) return Json(new { result = false });
            order.StartedDate = DateTime.Now;
            order.Deadline = DateTime.Now.AddDays(order.TimeToFinish);
            order.Status = (int)OrderStatusV2.InProgress;
            order.ModifiedDate = DateTime.Now;
            _OrderService.Update(order);
            var m = new MMessage()
            {
                Content = Resources.Resource.SystemMessageAcceptOrder,
                Date = DateTime.Now,
                Info = new MMessageEmbedInfo()
                {
                    Type = (int)EEmbedInfoType.Accept
                },
                IsRead = false,
                ParentID = MessageHelper.BuildShortIDOrder(order.ID),
                ReceiverID = (order.SellerID == user.ID ? order.BuyerID : order.SellerID),
                SenderID = user.ID,
                Type = (int)(order.Type == (int)OrderType.PROVIDE ? MessageType.ORDER_PROVIDE : MessageType.ORDER_REQUEST)
            };
            _MMessageService.Add(m);
            return Json(new { result = true });
        }

        public ActionResult MakeDeliveryOrder(int orderid, string linkresult)
        {
            if (!User.Identity.IsAuthenticated) return Json(new { result = false });
            var user = UtilityService.GetLoginUser(_UserService, User);
            var order = _OrderService.GetById(orderid);
            if (order == null) return Json(new { result = false });
            order.Status = (int)OrderStatusV2.WaitDone;
            order.ModifiedDate = DateTime.Now;
            _OrderService.Update(order);
            var m = new MMessage()
            {
                Content = Resources.Resource.SystemMessageDeliveryOrder,
                Date = DateTime.Now,
                Info = new MMessageEmbedInfo()
                {
                    Type = (int)EEmbedInfoType.Delivery,
                    Download = linkresult
                },
                IsRead = false,
                ParentID = MessageHelper.BuildShortIDOrder(order.ID),
                ReceiverID = (order.SellerID == user.ID ? order.BuyerID : order.SellerID),
                SenderID = user.ID,
                Type = (int)(order.Type == (int)OrderType.PROVIDE ? MessageType.ORDER_PROVIDE : MessageType.ORDER_REQUEST)
            };
            _MMessageService.Add(m);
            return Json(new { result = true });
        }

        public ActionResult MakeRejectOrder(int orderid)
        {
            if (!User.Identity.IsAuthenticated) return Json(new { result = false });
            var user = UtilityService.GetLoginUser(_UserService, User);
            var order = _OrderService.GetById(orderid);
            if (order == null) return Json(new { result = false });
            order.Status = (int)OrderStatusV2.Rejected;
            order.ModifiedDate = DateTime.Now;
            _OrderService.Update(order);
            var m = new MMessage()
            {
                Content = Resources.Resource.SystemMessageRejectOrder,
                Date = DateTime.Now,
                Info = new MMessageEmbedInfo()
                {
                    Type = (int)EEmbedInfoType.Rejected
                },
                IsRead = false,
                ParentID = MessageHelper.BuildShortIDOrder(order.ID),
                ReceiverID = (order.SellerID == user.ID ? order.BuyerID : order.SellerID),
                SenderID = user.ID,
                Type = (int)(order.Type == (int)OrderType.PROVIDE ? MessageType.ORDER_PROVIDE : MessageType.ORDER_REQUEST)
            };
            _MMessageService.Add(m);
            return Json(new { result = true });
        }

        public ActionResult MakeDoneOrder(int orderid)
        {
            if (!User.Identity.IsAuthenticated) return Json(new { result = false });
            var user = UtilityService.GetLoginUser(_UserService, User);
            var order = _OrderService.GetById(orderid);
            if (order == null) return Json(new { result = false });
            order.Status = (int)OrderStatusV2.Done;
            order.ModifiedDate = DateTime.Now;
            _OrderService.Update(order);
            return Json(new { result = true });
        }
    }
}